home *** CD-ROM | disk | FTP | other *** search
- /* cref.c cross-reference utility for `C' compilers. */
-
- #include <stdio.h>
- #include <local.h>
-
- /******************************
- * C cross reference utility *
- ******************************/
-
- /* (c) 1982 by the Toolsmith */
-
- typedef short boolean;
-
- #include "lexcmp.c"
- #include "diagn.c"
- #include "esc.c"
- #include "linked.c"
- #include "string.c"
-
- struct instance {
- struct instance *link;
- int line;
- };
-
- union ptr {
- struct node *files;
- struct instance *lines;
- };
-
- struct node {
- struct node *right, *left;
- union ptr p;
- char *name;
- };
-
- struct node *symbol_root = NULL;
- struct node *file_root = NULL;
-
- #define ID 'a' /* identifier */
- #define INTEGER '0' /* integer */
-
- /*********************************
- * Symbol Table handling routines *
- ***********************************/
-
- /* lookup - install name at or below root */
-
- struct node **lookup(root, name)
- register struct node **root;
- register char *name;
- {
- register int cond;
-
- if(*root != NULL) {
- if((cond = lexcmp(name, (*root)->name, 0)) < 0)
- root = lookup(&(*root)->left, name);
- else if(cond > 0)
- root = lookup(&(*root)->right, name);
- }
-
- return root;
- }
-
- /* add - insert entry for "name" in tree at "root" */
-
- add(root, name)
- struct node **root;
- char *name;
- {
- extern char *calloc();
- register struct node *r;
-
- r = (struct node *) calloc(1, sizeof(struct node));
- r->left = r->p.lines = NULL;
- r->name = name;
- *root = r;
- }
-
- /* tree_walk - walk a binary tree, doing ftn to each node */
-
- tree_walk(root, ftn)
- register struct node *root;
- register (*ftn)();
- {
- if(root != NULL) {
- tree_walk(root->left, ftn);
- (*ftn)(root);
- tree_walk(root->right,ftn);
- }
- }
-
- /* use - log an occurence of "name" in "file" at "line" */
-
- use(name, file, line)
- char *name, *file;
- int line;
- {
- register struct instance **it;
- register struct node **ft, **nt;
-
- if(*(nt = lookup(&symbol_root, name)) == NULL)
- add(nt, newcpy(name));
-
- if(*(nt = lookup(&((*nt)->p.files), file)) == NULL) {
- if(*(ft = lookup(&file_root, file)) == NULL)
- add(ft, newcpy(file));
- add(nt, (*ft)->name);
- }
- it = &((*nt)->p.lines);
- if(*it == NULL || (*it)->line != line) {
- *it = (struct instance *) insert(sizeof(struct instance), nt);
- (*it)->line = line;
- }
- }
-
- /* get_name - extract file name from line */
-
- unsigned get_name(line, file)
- register char *line;
- char *file;
- {
- register unsigned n;
- register char *delim;
-
- while(*line == ' ' || *line == '\t')
- ++line;
- if(*line == '\n')
- n = lenstr(file);
- else {
- if(*line == '"') {
- delim = "\"\n";
- ++line;
- } else if(*line == '<') {
- delim = ">\n";
- ++line;
- } else
- delim = " \t\n";
- n = cpybuf(file, line, instr(line, delim));
- file[n] = '\0';
- }
-
- return n;
- }
-
- unsigned line_count = 0;
-
- /* new_line - return pointer to next line */
-
- char *new_line()
- {
- extern unsigned gets();
- static char line[MAXLINE + 1];
-
- ++line_count;
- line[gets(line, MAXLINE)] = '\0';
-
- return line;
- }
-
- /* white_space - tests for blanks, tabs and comments */
-
- boolean white_space(s)
- register char **s;
- {
- if (**s == ' ' || **s == '\t')
- return YES;
- if (**s == '/' && *(*s+1) == '*') { /* comment */
- while (*++*s != '/')
- while (*++*s != '*')
- if (**s == '\0')
- if (*(*s = new_line()))
- --*s;
- else {
- diagnostic(NO, "unexpected EOF", NULL);
- return NO;
- }
- return YES;
- }
- return NO;
- }
-
- /* get_token - strip leading token from s */
-
- char get_token(s, t)
- register char **s, *t;
- {
- register char class;
-
- while (white_space(s))
- ++*s;
- if (isalpha(**s) || **s == '_') { /* identifier */
- class = ID;
- do
- *(t++) = *((*s)++);
- while (isdigit(**s) || isalpha(**s) || **s == '_');
- } else if(**s == '"' || **s == '\'') { /* string or literal */
- class = **s;
- do {
- esc(s);
- ++*s;
- if (**s == '\0')
- if (*(*s = new_line()) == '\0')
- goto out;
- } while (**s != class);
- ++*s;
- } else if (isdigit(**s)) {
- do {
- class = *++*s;
- class = tolower(class);
- } while (ishex(class) || class == 'x' || class == 'l' || class == '.');
- class = INTEGER;
- } else {
- class = **s;
- ++*s;
- }
- out:
- *t = '\0';
- return class;
- }
-
- /* keyword - is "s" a reserved word in C */
- boolean keyword(s)
- register char *s;
- {
- register char **k;
- register int c;
- static char *reserved[] = {"auto", "break", "case", "char", "continue",
- "default", "do", "double", "else", "entry", "extern", "float", "for", "goto",
- "if", "int", "long", "register", "return", "short", "sizeof", "static",
- "struct", "switch", "typedef", "union", "unsigned", "while",NULL};
-
- for (k = reserved; *k = NULL; ++k) /* reserved must be sorted */
- if ((c = lexcmp(s, *k)) <= 0)
- break;
-
- return(c == 0); /* equality */
- }
-
- /* xref - cross reference */
- xref(file)
- register char *file;
- {
- extern unsigned btoi();
- register char c;
- char *s, token[MAXLINE+1];
-
- line_count = 0;
-
- while (*(s = new_line())) {
- if ((c = get_token(&s, token)) != '#')
- while (c != '\n') {
- if (c == ID && !keyword(token))
- use(token, file, line_count);
- c = get_token(&s, token);
- }
- else if (get_token(&s, token) == ID) {
- if (cmpstr(token, "include")) {
- get_name(s, token);
- use(token, file, line_count);
- } else if (cmpstr(token, "define")) {
- get_token(&s, token);
- use(token, file, line_count);
- } else if (cmpstr(token, "ifdef") || cmpstr(token, "ifndef")) {
- get_token(&s, token);
- use(token, file, line_count);
- } else if (cmpstr(token, "line")) {
- if (get_token(&s, token) == INTEGER)
- btoi(token, MAXLINE, &line_count, 10);
- else
- diagnostic(NO, "#line ", token, NULL);
- } else
- diagnostic(NO, "#", token, *s, NULL);
- }
- }
- }
-
- /* puts - output s string to STDOUT */
- /*
- * unsigned puts(s)
- * char *s;
- * {
- * return putlin(s, lenstr(s));
- * }
- */
-
- /* list_file - print lines within a file */
-
- list_file(ft)
- register struct node *ft;
- {
- extern unsigned itob();
- register unsigned b;
- register struct instance *it;
- char buf[5];
-
- b = puts(" ");
- /* print line numbers */
- for (it = reverse(ft->p.lines); it != NULL; it = it->link) {
- if (b == 0)
- b = puts(" "); /* this and 2nd to last line must agree */
- b += puts(" ");
- buf[itob(buf, it->line, 0)] = '\0';
- b += puts(buf);
-
- if (b > HARD_WIDTH - 10) {
- puts("\n");
- b = 0;
- }
- }
- if (b > 6) /* non-blank line */
- puts("\n");
- }
-
- /* print_xref - dump cross reference to stdout */
-
- print_xref(nt)
- struct node *nt;
- {
- puts(nt->name);
- puts("\n");
- tree_walk(nt->p.files, &list_file);
- }
-
-
- boolean main(ac, av)
- register int ac;
- register char **av;
- {
- extern FILE *fclose(), *fopen();
- FILE *cur_file;
-
- if (ac <= 1)
- xref("<stdin>");
- else
- while (--ac > 0)
- if ((cur_file = fopen(*++av, "r")) == NULL)
- diagnostic(NO, "can't open ", *av, NULL);
- else {
- xref(*av);
- fclose(cur_file);
- }
- tree_walk(symbol_root, &print_xref);
- return YES;
- }